﻿package com.guavestudios.fcfg {
	import com.guavestudios.fcfg.readers.FcfgDefaultModifier;
	import com.guavestudios.fcfg.readers.FcfgDefaultReader;
	import com.guavestudios.fcfg.readers.FcfgXmlReader;
	import com.guavestudios.fcfg.readers.ISettingModifier;
	import com.guavestudios.fcfg.readers.ISettingReader;
	import flash.events.EventDispatcher;
	/**
	 * ...
	 * @author maze | guavestudios.com
	 */
	public class Fcfg extends EventDispatcher {
		
		/**
		 * multition initializer
		 */
		static private var _instanceUnique:int = -1;
		static private var _instances:Object = { };
		static public function getInstance(id:String = "default"):Fcfg {
			var conf:Fcfg = _instances[id];
			if (conf == null) {
				_instances[id] = conf = new Fcfg();
				conf.configName = id;
			}
			return conf;
		}
		static public function getUniqueInstance():Fcfg {
			_instanceUnique++;
			return getInstance("fcfg_" + _instanceUnique.toString());
		}
		
		protected var _orderIncrement:int = 0;
		protected var _configName:String;
		protected var _settings:Object;
		protected var _readers:Array;
		protected var _defalutModifier:ISettingModifier;
		
		public function Fcfg() {
			_settings = {};
			_readers = [];
			defalutModifier = new FcfgDefaultModifier();
			
		}
		
		//reader management
		public function getReaderCount():int {
			return _readers.length;
		}
		public function getReaderAt(index:int):ISettingReader {
			return _readers[index];
		}
		public function addReader(reader:*):ISettingReader {
			var rdr:ISettingReader;
			if (reader is ISettingReader) {
				rdr = reader;
			}
			else if (reader is XML) {
				rdr = new FcfgXmlReader(reader as XML);

			} else if (reader is Object) {
				rdr = new FcfgDefaultReader(reader);
				
			} else {
				throw new Error("Error: addReader wrong argument");
			}
			_readers.push(rdr);
			rdr.order = _orderIncrement++;
			_readers.sortOn(["priority","order"], Array.NUMERIC);
			rdr.fcfg = this;
			//reader.
			return rdr;
		}
		
		//settings
		public function setSetting(id:String, value:*):void {
			var o:*= _settings[id];
			_defalutModifier.setSetting(id, value);
			dispatchSettingChanged(id,value,o);
		}
		public function getSetting(id:String):* {
			if (!hasSetting(id)) updateSetting(id);
			return _settings[id];
		}
		public function hasSetting(id:String):Boolean {
			return _settings.hasOwnProperty(id);
		}
		public function removeSetting(id:String):void {
			_defalutModifier.removeSetting(id);
			updateSetting(id);
		}
		
		public function updateSetting(id:String):void {
			var rdr:ISettingReader;
			for (var i:int = _readers.length - 1; i >= 0; i--) {
				rdr = _readers[i];
				if (rdr.hasSetting(id)){
					_settings[id] = rdr.getSetting(id);
					return;
				}
			}
			
			//setting was not found
			delete _settings[id];
		}
		
		//settings shortcuts
		public function g(id:String):*{
			return getSetting(id);
		}
		public function s(id:String, v:*):void {
			setSetting(id, v);
		}
		public function h(id:String):Boolean {
			return hasSetting(id);
		}
		public function r(id:String):void {
			removeSetting(id);
		}
		public function dispatchSettingChanged(id:String,newS:*,oldS:*):void {
			if (hasEventListener(FcfgEvent.SETTING_CHANGED)) {
				dispatchEvent(new FcfgEvent(FcfgEvent.SETTING_CHANGED, id, oldS,newS));
			}
		}
		
		override public function toString():String {
			var str:String = "Fcfg (";
			for (var i:String in _settings) {
				str += "\n   "+i+" = "+_settings[i];
			}
			str += "\n)";
			return str;
		}
		
		public function get defalutModifier():ISettingModifier { return _defalutModifier; }
		public function set defalutModifier(value:ISettingModifier):void {
			_defalutModifier = value;
			_defalutModifier.priority = 20;
			_defalutModifier.fcfg = this;
			addReader(_defalutModifier);
		}
		
		public function get configName():String { return _configName; }
		
		public function set configName(value:String):void {
			_configName = value;
		}
	}

}